﻿using System.Diagnostics;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Spreadsheet;

namespace Haimen.Excel;

internal class SheetReaderImpl(OpenXmlReader _xmlRead) : LgeSheetReader {

  public void Dispose() => _xmlRead.Dispose();

  public void SkipToRow(int targetRow) {
    var getRowNum = () => {
      foreach (OpenXmlAttribute attr in _xmlRead.Attributes) {
        if ("r".Equals(attr.LocalName)) {
          string? val = attr.Value;
          if (val == null) {
            break;
          }
          return int.Parse(val);
        }
      }
      return -1;
    };

    while (_xmlRead.Read()) {
      if (_xmlRead.IsEndElement) {
        continue;
      }
      if (_xmlRead.ElementType == typeof(Row)) {
        int curRow = getRowNum();
        Debug.Assert(curRow > 0);

        if (curRow == targetRow) {
          return;
        }
        Debug.Assert(curRow < targetRow);
      }
    }
  }

  public bool ReadRow() {
    while (_xmlRead.Read()) {
      if (_xmlRead.IsEndElement) {
        continue;
      }
      if (_xmlRead.ElementType == typeof(Row)) {
        //Console.WriteLine(string.Join(',', _xmlRead.Attributes.Select(a => $"{a.LocalName}={a.Value}")));
        return true;
      }
      _xmlRead.Skip();
    }
    return false;
  }

  public LgeRowAttr GetRowAttr() {
    string refer = "r";
    foreach (OpenXmlAttribute attr in _xmlRead.Attributes) {
      if (refer.Equals(attr.LocalName)) {
        refer = attr.Value!;
        break;
      }
    }
    return new(refer);
  }

  public bool ReadCell() {
    while (_xmlRead.Read()) {
      if (_xmlRead.IsEndElement) {
        if (_xmlRead.ElementType == typeof(Row)) {
          return false;
        }
        continue;
      }
      if (_xmlRead.ElementType == typeof(Cell)) {
        return true;
      }
    }
    return false;
  }

  public LargeExcelCell ConsumeCell() {
    string colRef = "";
    string cellType = "n";

    foreach (OpenXmlAttribute attr in _xmlRead.Attributes) {
      if ("r".Equals(attr.LocalName)) {
        colRef = attr.Value!;
        continue;
      }
      if ("t".Equals(attr.LocalName)) {
        cellType = attr.Value!;
        continue;
      }
    }

    Debug.Assert(colRef.Length > 0);
    while (_xmlRead.Read()) {
      if (_xmlRead.IsEndElement) {
        continue;
      }

      if (_xmlRead.ElementType == typeof(CellValue)
        || _xmlRead.ElementType == typeof(Text)) {
        break;
      }
    }

    string valText = _xmlRead.GetText();
    return new(colRef, cellType, valText);
  }
}
